#include "stdafx.h"
/*

@returns error code
*/
int get_poly(std::vector<graph_basic::lat_lon_t> point_list, std::string path_type, std::list<graph_basic::lat_lon_t>& result)
{
    //Getting nearest vertices to start and finish
    graph_virtual::global_data_t& global = graph_virtual::global::get_instance(); //get reference to global data
    graph_basic::lat_lon_t start_vertex_lat = point_list[0]; 
    graph_basic::lat_lon_t start_vertex_lng = point_list[1];
    graph_basic::lat_lon_t finish_vertex_lat = point_list[2]; 
    graph_basic::lat_lon_t finish_vertex_lng = point_list[3];
    
    std::cout << "Processing request:" << std::endl
        << "   s_lat: " << start_vertex_lat << std::endl 
        << "   s_lon: " << start_vertex_lng << std::endl
        << "   f_lat: " << finish_vertex_lat << std::endl 
        << "   f_lng: " << finish_vertex_lng << std::endl 
        << "   p_type: " << path_type << std::endl;

    global.set_new_view(path_type);

    graph_basic::vertex_id_pair_t start_finish_pair;
    
    graph_basic::graph_view_ptr_t view_start = global.get_current_view_for_graph(
      graph_virtual::details::virtual_graph_friend_t::get_bucket(
         *global.graph_,
         graph_virtual::details::virtual_graph_friend_t::
         find_bucket(*global.graph_, graph_basic::point_t(start_vertex_lat, start_vertex_lng))
      ).get_graph_ptr()
    );
    graph_basic::graph_view_ptr_t view_finish = global.get_current_view_for_graph(
      graph_virtual::details::virtual_graph_friend_t::get_bucket(
         *global.graph_,
         graph_virtual::details::virtual_graph_friend_t::
         find_bucket(*global.graph_, graph_basic::point_t(finish_vertex_lat, finish_vertex_lng))
      ).get_graph_ptr()
    );
    
    if (view_start->get_graph().get_graph_id() != view_finish->get_graph().get_graph_id())
    {
       start_finish_pair.first = 
         graph_basic::nearest_vertex(*view_start, graph_basic::point_t(start_vertex_lat, start_vertex_lng));
       start_finish_pair.second = 
         graph_basic::nearest_vertex(*view_finish, graph_basic::point_t(finish_vertex_lat, finish_vertex_lng));
    }
    else
    {
      start_finish_pair = 
      graph_basic::nearest_vertices(*view_start, graph_basic::point_t(start_vertex_lat, start_vertex_lng),
                                                graph_basic::point_t(finish_vertex_lat, finish_vertex_lng));
    }
    
    
    graph_basic::vertex_t& start_vertex = global.current_view_->get_vertex_by_id(start_finish_pair.first);
    graph_basic::vertex_t& finish_vertex = global.current_view_->get_vertex_by_id(start_finish_pair.second);
    
    std::cout << "added start vertex:"  << std::endl
        << "   buck_id: " << start_vertex.get_id().graph_id_ << std::endl
        << "   in_buck_id: " << start_vertex.get_id().vertex_in_graph_id_ << std::endl
        << "   lat: " << start_vertex.get_point().lat_ << std::endl 
        << "   lon: " << start_vertex.get_point().lon_ << std::endl;
        
    std::cout << "added finish vertex:" << std::endl
        << "   buck_id: " <<  finish_vertex.get_id().graph_id_ << std::endl
        << "   in_buck_id: " <<  finish_vertex.get_id().vertex_in_graph_id_ << std::endl
        << "   lat: " <<  finish_vertex.get_point().lat_ << std::endl
        << "   lon: " <<  finish_vertex.get_point().lon_ << std::endl;

    ///Calling shortest path algorithm
    //AstarSearch as(*global.current_view_, start_vertex, finish_vertex, true);
    //vertex_id_t mid_id = as.Run2(true, 0);
    graph_virtual::astar_search::astar_search_t<
      graph_virtual::astar_search::astar_mode_e::release, 
      graph_virtual::astar_search::astar_direction_e::bidirectional
    > as(global.current_view_, start_vertex, finish_vertex);
    as.run(true, 0);

    //Come back and take the shortest path    
    if (as.is_all_ended())
    {   
        graph_virtual::astar_search::fill_shpath(as, result);
        return 0;
    }   
    else
    {
        return 1; //"err_code_1"
    }
}

int handle_request(fcgi::request& req)
{
   req.load(fcgi::parse_all);
   fcgi::response resp;
   resp << fcgi::content_type("text/plain");      
   //resp << "<H1>Hello world!!!</H1>";
   
   std::vector<graph_basic::lat_lon_t> user_points;
   user_points.push_back( boost::lexical_cast<graph_basic::lat_lon_t>(req.get["lat1"]) );
   user_points.push_back( boost::lexical_cast<graph_basic::lat_lon_t>(req.get["lng1"]) );
   user_points.push_back( boost::lexical_cast<graph_basic::lat_lon_t>(req.get["lat2"]) );
   user_points.push_back( boost::lexical_cast<graph_basic::lat_lon_t>(req.get["lng2"]) );   
   std::string path_type;
   path_type = req.get["path-type"];
   std::list<graph_basic::lat_lon_t> sh_path;
   int status = get_poly(user_points, path_type, sh_path);
   if (!status)
   {
       std::cout << "successfully processed" << std::endl;
       // making json [lat1, lng1, .., lati, lngi, ..]
       resp << "["; 
       std::list<graph_basic::lat_lon_t>::iterator it = sh_path.begin();
       resp << boost::lexical_cast<std::string>(*it);
       ++it;
       for(; it != sh_path.end(); ++it)
       {
          resp << ",";
          resp << boost::lexical_cast<std::string>(*it);
       }
       resp << "]";
   }
   else
   {
      std::cout << "error " << status << std::endl;
      resp << "\"err_code_";
      resp << boost::lexical_cast<std::string>(status);
      resp << "\"";
   }
   //resp << "Response content-length == " << resp.content_length();
   return fcgi::commit(req, resp);
}

